package com.hw.protocol.tool.decode;

import com.hw.protocol.tool.model.entity.HwProtocol;
import com.hw.protocol.tool.model.Result;
import com.hw.protocol.tool.util.CodeUtil;
import com.hw.protocol.tool.util.CrcUtil;
import io.netty.buffer.ByteBuf;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * @author : lihy
 * @date : 2024/3/12 10:28
 * description: 昊威协议解码
 */
@Slf4j
@Component
public class HwDecode implements IDecode {

    @Override
    public Result decode(byte[] bytes) {
        ByteBuf in = wrapBytes(bytes);
        try {
            int length = in.capacity();

            byte fh = in.readByte();
            if (fh != (byte) 0xfd) {
                in.release();
                return Result.error("帧头错误");
            }
            short version = in.readShort();

            byte[] noCrc = new byte[length - 2];
            in.getBytes(0, noCrc);
            //CRC
            byte[] crcBytes = new byte[2];
            in.getBytes(length - 2, crcBytes);

            //crc验证
            byte[] calCrc = CrcUtil.getCrcBytes(noCrc, true);
            if (calCrc[0] != crcBytes[0] || calCrc[1] != crcBytes[1]) {
                in.release();
                return Result.error("crc验证错误");
            }

            HwProtocol pro = new HwProtocol();
            //帧头
            pro.setFh(fh);
            //版本
            pro.setVersion(version);
            //数据长度
            pro.setLength(in.readShortLE());
            //功能码
            pro.setFunctionCode(in.readByte());

            //设备编码 ascii码
            byte[] devBytes = new byte[8];
            in.readBytes(devBytes);
            pro.setDevSerial(CodeUtil.bytesToAscii(devBytes));

            //通道
            int chunnelSerial = in.readShortLE();
            pro.setChunnelSerial(chunnelSerial + "");
            //数据
            byte[] data = new byte[length - 18];
            in.readBytes(data);
            pro.setData(data);
            //CRC
            pro.setCrc(crcBytes);

            in.release();
            return Result.success(pro);
        } catch (Exception e) {
            in.release();
            log.error(e.getMessage(), e);
            return Result.error("解析失败");
        }
    }
}
